// import * as Cesium from 'cesium'
import MarkerStyle from "../style/MarkerStyle";

/**
 * 标记（贴地）
 */
export default class Marker {
  // 实体类型
  static ENTITY_TYPE = {
    POINT: "point",
    BILLBOARD: "billboard",
  };

  // 订阅消息类型
  static EVENT_TYPE = {
    MOVE_END: "moveEnd",
  };
  /**
   * 渲染点，并且点会自动贴合到模型表面
   * 注意： 如果需要贴合模型表面, 需要等模型加载完之后才能调用本方法,加载完成事件详见 onLoaded
   * @param longitude 经度(required)
   * @param latitude 纬度(required)
   * @param height 高度(米) 不传或者传null、undefined时，自动贴合到模型表面
   * @param id 唯一id
   * @param imgUrl 图标
   * @param imgWidth 图标宽
   * @param style 样式属性，详见MarkerStyle
   * @param viewer
   */
  constructor(options) {
    const {
      viewer,
      id,
      longitude,
      latitude,
      height,
      style,
      deptDistance = 2000,
    } = options || {};
    this.id = id;
    this.positionArr = [];
    this.lerpValue = 70;
    this.isMoving = false; // 改变位置时，是否正在执行
    const { iconStyle, textStyle } = style || new MarkerStyle();
    this.text = textStyle.text;
    this.marker = viewer.entities.add({
      id,
      billboard: {
        image: iconStyle.url,
        width: iconStyle.width,
        height: iconStyle.height,
        pixelOffset: iconStyle.pixelOffset,
        disableDepthTestDistance: deptDistance,
        scaleByDistance: new Cesium.NearFarScalar(2000, 1.0, 1e4, 0),
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      },
      label: {
        text: textStyle.text,
        font: textStyle.font,
        fillColor: textStyle.fillColor,
        outlineColor: textStyle.outlineColor,
        outlineWidth: textStyle.outlineWidth,
        showBackground: textStyle.showBackground,
        backgroundColor: textStyle.backgroundColor,
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        disableDepthTestDistance: deptDistance,
        horizontalOrigin: textStyle.horizontalOrigin,
        // 垂直方向以底部来计算标签的位置
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        scaleByDistance: new Cesium.NearFarScalar(1500, 1.0, 1e4, 0),
        // 偏移量
        pixelOffset: textStyle.pixelOffset,
      },
      clampToGround: true,
    });
    let fromDegrees = null;
    if (height) {
      fromDegrees = new Cesium.Cartesian3.fromDegrees(
        longitude,
        latitude,
        height,
      );
    } else {
      fromDegrees = viewer.scene.clampToHeight(
        Cesium.Cartesian3.fromDegrees(longitude, latitude),
      );
    }
    if (fromDegrees) {
      this.positionArr.push(fromDegrees);
    }
    this.marker.position = fromDegrees;
  }

  /**
   * 设置marker的label文本
   * @param text
   */
  setText(text) {
    this.marker.label.text = text;
  }

  /**
   * 在建筑图标后追加人数
   * @param perpleNum
   */
  addPeopleNumText(perpleNum) {
    this.marker.label.text = this.text + "   " + perpleNum + "人";
  }

  /**
   * 更新点位置
   * @param longitude 经度（度）(required)
   * @param latitude 纬度（度）(required)
   * @param height 高度(米) 不传或者传null、undefined时，自动贴合到模型表面
   * @param isAnimation 是否带动画更新点位，为false就是瞬移过去
   * @param isUpdate 是否更新该点位，false就不更新，在页面切出后不更新
   */
  updatePosition(
    { longitude, latitude, height },
    { isAnimation = true, isUpdate = true },
  ) {
    let fromDegrees = null;
    fromDegrees = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);
    if (isAnimation) {
      this.appendToPosition(fromDegrees, isUpdate);
    } else {
      this.marker.position = fromDegrees;
    }
  }

  /**
   * 增加点位更新位置的方法
   * @param position 点位位置 Cartesian3
   * @param isUpdate 是否更新
   */
  appendToPosition(position, isUpdate) {
    if (isUpdate) {
      // console.log('页面是激活状态，进行更新点操作', isUpdate)
      const lastIndex = this.positionArr.length - 1;
      if (
        JSON.stringify(position) === JSON.stringify(this.positionArr[lastIndex])
      ) {
        // console.log('更新的位置和最后一个位置一样，不操作,', position, this.positionArr, this.id)
        return;
      }
      const len = this.positionArr.push(position);
      if (len >= 2 && !this.isMoving) {
        this.moveTo(this.positionArr[0], this.positionArr[1]);
      } else if (len == 1) {
        this.marker.position = position;
      }
    } else {
      this.positionArr = [];
    }
  }

  /**
   * 单次移动结束后的方法
   */
  moveEnd() {
    this.isMoving = false;
    this.positionArr.splice(0, 1);
    if (this.positionArr.length >= 2) {
      this.moveTo(this.positionArr[0], this.positionArr[1]);
    }
  }

  /**
   * 移动到某个点
   * @param start 开始点位置 Cartesian3
   * @param end 结束点位置 Cartesian3
   */
  moveTo(start, end) {
    // 插值的数量
    let factor = 0;
    this.isMoving = true;
    const t = Date.now();
    this.marker.position = new Cesium.CallbackProperty(() => {
      if (factor >= this.lerpValue) {
        if (this.isMoving) {
          this.moveEnd();
        }
        return end;
      }
      factor++;
      // 动态更新位置
      return Cesium.Cartesian3.lerp(
        start,
        end,
        factor / this.lerpValue,
        new Cesium.Cartesian3(),
      );
    }, false);
  }

  /**
   * 设置样式
   * @param style 样式属性，详见MarkerStyle
   */
  setStyle(style) {
    const { iconStyle, textStyle } = style || new MarkerStyle();
    this.marker.billboardimage = iconStyle.url;
    this.marker.billboardwidth = iconStyle.width;
    this.marker.billboardheight = iconStyle.height;
    this.marker.billboardpixelOffset = iconStyle.pixelOffset;
    this.marker.label.text = textStyle.text;
    this.marker.label.font = textStyle.font;
    this.marker.label.fillColor = textStyle.fillColor;
    this.marker.label.outlineColor = textStyle.outlineColor;
    this.marker.label.outlineWidth = textStyle.outlineWidth;
    this.marker.label.showBackground = textStyle.showBackground;
    this.marker.label.backgroundColor = textStyle.backgroundColor;
    this.marker.label.pixelOffset = textStyle.pixelOffset;
  }

  /**
   * 设置图标样式
   * @param iconStyle
   */
  setIconStyle(iconStyle) {
    this.marker.billboardimage = iconStyle.url;
    this.marker.billboardwidth = iconStyle.width;
    this.marker.billboardheight = iconStyle.height;
    this.marker.billboardpixelOffset = iconStyle.pixelOffset;
  }

  /**
   * 设置字体样式
   * @param textStyle
   */
  setTextStyle(textStyle) {
    this.marker.label.fillColor = textStyle.fillColor;
    this.marker.label.outlineColor = textStyle.outlineColor;
    this.marker.label.outlineWidth = textStyle.outlineWidth || 4;
  }

  /**
   * 设置Marker是否可见
   * @param bool visibility
   */
  setVisible(visibility) {
    this.marker.billboard.show = visibility;
    this.marker.label.show = visibility;
  }
}
